package com.ly.mp.busicen.rule.flow;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.expression.EvaluationContext;

import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.ly.mp.busicen.common.context.BusicenException;
import com.ly.mp.busicen.rule.flow.IFlowResultCtn.Risultato;
import com.ly.mp.busicen.rule.flow.action.IAction;
import com.ly.mp.busicen.rule.instrumentation.IFlowInstrumentation;

public class FireFlow implements IFireFlow{	
	
	private final static Logger log = LoggerFactory.getLogger(FireFlow.class);
	
	@Autowired
	IActionContainer actionContainer;
	
	@Autowired
	IFlowExecute flowExecute;
	
	@Autowired
	IFlowInstrumentation instrumentation;

	@Override
	public IFlowResultCtn fire(String flow,Map<String, Object> data) {
		return fire(flow, null, data);
	}
	
	/**
	 * 
	 * @author wangzhen
	 * @param flow 规则code
	 * @param brand null
	 * @param data 你的数据参数
	 * @param rid 随机生成的id
	 * @return IFlowContext
	 */
	public IFlowContext buildContext(String flow,String brand,Map<String, Object> data,String rid) {
		FlowContext context = FlowContext.create(flow, data);
		context.dataVolume().end().put("bupks", new ArrayList<Object>());
		//增加用户模式
		List<IAction> actions = actionContainer.flowActions(flow,FlowUserMode.currentContext(brand));
		
		((FlowVolume)context.flowVolume()).setRid(rid);
		EvaluationContext sec = sec(context.dataVolume());		
		Optional.of(actions).ifPresent(m->{
			m.stream().forEach(n->{
				n.extention().put(IAction.EXTKEY_RID, rid);
				n.extention().put(IAction.EXTKEY_SPEL, sec);
			});
		});
		context.getFlowVolume().setActions(actions);
		return context;
	}
	// 里面有data (用户传的数据) 和 user
	private EvaluationContext sec(IDataVolume dataVolume) {
		EvaluationContext sec =FlowSpelUtil.buildSpelContext(dataVolume, null);
		return sec;
	}
	
	
	public IFlowResultCtn resultWrapper(IFlowResultCtn result) {
		if (result instanceof FlowResultCtn) {
			
		}
		return result;
	}

	@Override
	public IFlowResultCtn fireExcpt(String flow, Map<String, Object> data) {
		return fireExcpt(flow, null, data);
	}

	@Override
	public IFlowResultCtn fireExcpt(String flow, String brand, Map<String, Object> data) {
		IFlowResultCtn result = fire(flow,brand, data);
		if (result.risultato().equals(Risultato.BREAK)) {
			throw BusicenException.create(result.breakResult().message());
		}		
		return result;
	}

	/**
	 * 
	 * @MethodName: fire
	 * @Description: TODO
	 * @param flow  BUSINESSFLOW_SENCECODE 字段, 就是你规则的编码(业务场景编码)
	 * @param brand 一般为null
	 * @param data 你传的数据
	 */
	@Override
	public IFlowResultCtn fire(String flow, String brand, Map<String, Object> data) {
		IFlowResultCtn result =null;
		try {
			String rid = IdWorker.get32UUID();
			instrumentation.beginFlow(flow, brand, data,rid);
			IFlowContext context = buildContext(flow,brand, data,rid);
			instrumentation.endBuildContext(context);
			result = flowExecute.process(context);			
			if (result.risultato().equals(Risultato.EXCPT)) {
				if (result.excpt() instanceof BusicenException) {
					throw (BusicenException)result.excpt();
				}
				if (result.excpt() instanceof RuntimeException) {
					throw (RuntimeException)result.excpt();
				}
				throw new RuntimeException(result.excpt());
			}
			return result;
		} finally {
			instrumentation.endFlow(result);
			try {
				String actionRunHis = result.resultsStream().map(m->m.action()).collect(Collectors.joining("->"));
				String riso = "S";
				if(result.risultato().equals(Risultato.BREAK)) {
					riso="B";
				}else if(result.risultato().equals(Risultato.EXCPT)) {
					riso="E";
				}else {
					riso="S";
					actionRunHis+="->EXIT";
				}
				log.info("流程【{}】执行记录【{}】【{}】",flow,riso,actionRunHis);
			}catch(Exception e) {
				
			}
		}
		
	}

}
